#include <iostream>
#include <vector>
#include <boost/filesystem.hpp>
#include "util.hpp"
#include"index.hpp"
#include<boost/algorithm/string/case_conv.hpp>
// 输入型用const &
// 输出型用*
// 输入输出型用&
typedef struct DocInfo
{
    std::string title_;
    std::string content;
    std::string url_;
} DocInfo_t;
const std::string input_path = "date/input";
const std::string output_path = "date/raw_html/raw.txt";
const std::string repalace_url = "https://boost.org/doc/libs/1_78_0/doc";
bool EnumFiles(const std::string input_path, std::vector<std::string> *file_names);
bool ParseHtml(const std::vector<std::string> &file_names, std::vector<DocInfo_t> *results);
bool ParseTitle(const std::string &file_names, std::string *title);
bool ParseContent(const std::string &file_name, std::string *content);
bool ParseUrl(const std::string &file_name, std::string *url);
bool SaveHtml(const std::vector<DocInfo_t> &results, const std::string &output_path);
int main()
{
    // 提取文件名字
    std::vector<std::string> file_names;
    if (!EnumFiles(input_path, &file_names))
    {
        std::cerr << "get filenames error" << std::endl;
        return 1;
    }

    // 解析文件
    std::vector<DocInfo_t> results;
    if (!ParseHtml(file_names, &results))
    {
        std::cerr << "parse html error" << std::endl;
        return 2;
    }

    // 保存文件
    if(!SaveHtml(results, output_path))
    {
        std::cerr<<"save html error"<<std::endl;
        return 3;
    }



    return 0;
}

bool EnumFiles(const std::string input_path, std::vector<std::string> *file_names)
{
    namespace fs = boost::filesystem;
    fs::path root_path(input_path);
    if (!fs::exists(root_path))
    {
        std::cerr << "is not a effective path" << std::endl;
        return false;
    }

    fs::recursive_directory_iterator end;
    for (fs::recursive_directory_iterator item(root_path); item != end; item++)
    {
        if (!fs::is_regular(*item))
        {
            continue;
        }
        if (item->path().extension() != ".html")
        {
            continue;
        }
        // std::cout << "Debug: " << item->path().string() << std::endl;
        file_names->push_back(item->path().string());
    }
    return true;
}

bool ParseHtml(const std::vector<std::string> &file_names, std::vector<DocInfo_t> *results)
{
    //
    int count = 1;
    for (const std::string file_name : file_names)
    {
        DocInfo_t doc;
        if (!ParseTitle(file_name, &doc.title_))
        {
            std::cerr << file_name << " have not title or parse title error" << std::endl;
        }

        if (!ParseContent(file_name, &doc.content))
        {
            std::cerr << file_name << " have not content or parse content error" << std::endl;
        }
        // if(count-->0)
        // {
        //     std::cout<<"debug: "<<doc.content<<std::endl;
        // }

        if (!ParseUrl(file_name, &doc.url_))
        {
            std::cerr << file_name << " have not url or parse content error" << std::endl;
        }

        results->push_back(std::move(doc));
    }

    return true;
}

bool ParseTitle(const std::string &file_name, std::string *title)
{
    std::string out;
    if (!us_util::FileUtil::ReadFile(file_name, &out))
    {
        return false;
    }
    int start = out.find("<title>");
    if (start == std::string::npos)
    {
        std::cerr << "not found <title>" << std::endl;
        return false;
    }
    start += std::string("<title>").size();
    int end = out.find("</title>");
    if (end == std::string::npos)
    {
        std::cerr << "not found </title>" << std::endl;
        return false;
    }
    if (end - start < 0)
    {
        std::cerr << "</title> pos less than <title>" << std::endl;
        return false;
    }
    if(end-start==0)
    {
        //有个没标题的
         *title="index";
         return true;
    }
    *title=out.substr(start,end-start);
    // std::cout<<"debug: "<<*title<<std::endl;
    // if(title->empty())//?????
    // {
    //     std::cout<<file_name<<start<<"|"<<end-start<<std::endl;

    //     std::cout<<"none|"<<title->length()<<std::endl;
    // }
    return true;
}

bool ParseContent(const std::string &file_name, std::string *content)
{
    enum status
    {
        LABLE,
        CNOTENT
    };
    std::string out;
    if (!us_util::FileUtil::ReadFile(file_name, &out))
    {
        return false;
    }
    status s = status::LABLE;
    for (char c : out)
    {
        switch (s)
        {
        case status::LABLE:
            if (c == '>')
            {
                s = status::CNOTENT;
            }
            break;
        case status::CNOTENT:
            if (c == '<')
            {
                s = status::LABLE;
                break;
            }
            if (c == '\n')
                c = ' ';
            content->push_back(c);
            break;
        }
    }

    return true;
}

bool ParseUrl(const std::string &file_name, std::string *url)
{
    int start = file_name.find(input_path);
    start += input_path.size();
    std::string real_source_path = file_name.substr(start);
    (*url) = repalace_url + real_source_path;
    //std::cout << "debug: " << (*url) << std::endl;
    return true;
}

bool SaveHtml(const std::vector<DocInfo_t> &results, const std::string &output_path)
{
    #define SEP '\3'
    std::ofstream out(output_path,std::ios::out|std::ios::binary);//写形式 二进制方式写入不会解释反斜杠
    if(!out.is_open())
    {
        std::cerr<<output_path<<" open file error"<<std::endl;
        return false;
    }
    for(auto item:results)
    {
        std::string line;
        line+=boost::to_lower_copy(item.title_);
        line+=SEP;
        line+= boost::to_lower_copy(item.content);
        line+=SEP;
        line+=item.url_;
        line+='\n';
        out.write(line.c_str(),line.size());
    }
    out.close();
    return true;
}
